home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 1.iso / util / tsh091.zip / TSH.C < prev    next >
Text File  |  1994-03-13  |  41KB  |  2,089 lines

  1. /*
  2.  *  tsh - "Troy's Shell" - a command line interface for Windows.
  3.  *
  4.  *  Copyright (C) 1994  Troy Rollo <troy@cbme.unsw.EDU.AU>
  5.  *
  6.  *  This program is free software; you can redistribute it and/or modify
  7.  *  it under the terms of the GNU General Public License as published by
  8.  *  the Free Software Foundation; either version 2 of the License, or
  9.  *  (at your option) any later version.
  10.  *
  11.  *  This program is distributed in the hope that it will be useful,
  12.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  *  GNU General Public License for more details.
  15.  *
  16.  *  You should have received a copy of the GNU General Public License
  17.  *  along with this program; if not, write to the Free Software
  18.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  */
  20.  
  21. #include <windows.h>
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #include <fcntl.h>
  26. #include <dir.h>
  27. #include <dos.h>
  28. #include <sys/stat.h>
  29. #include <io.h>
  30. #include <time.h>
  31. #include <ctype.h>
  32. #include <errno.h>
  33. #include <toolhelp.h>
  34. #include <share.h>
  35. #include <sys/tkwin.h>
  36. #include <sys/tkern.h>
  37. #include <sys/tkexec.h>
  38. #include <sys/task.h>
  39. #include <sys/wait.h>
  40.  
  41.  
  42. char    *Months[] =
  43. {
  44.     "January",
  45.     "February",
  46.     "March",
  47.     "April",
  48.     "May",
  49.     "June",
  50.     "July",
  51.     "August",
  52.     "September",
  53.     "October",
  54.     "November",
  55.     "December"
  56. };
  57.  
  58. char    *Days[] =
  59. {
  60.     "Sunday",
  61.     "Monday",
  62.     "Tuesday",
  63.     "Wednesday",
  64.     "Thursday",
  65.     "Friday",
  66.     "Saturday"
  67. };
  68.  
  69. struct    redirection
  70. {
  71.     int    fd;
  72.     int    fdSource;
  73.     int    iMode;
  74.     char    *pchFile;
  75. };
  76.  
  77.  
  78.  
  79. int parse_command(char const *s);
  80. char *pwd(void);
  81.  
  82. static char tmpbuf[2048];
  83. static char buf[2048] = {0};
  84. static char title[80] = "tsh";
  85. static unsigned instance = 0;
  86. static    HWND    hWnd = 0;
  87. static    HWND    hWndOA;
  88. static    HINSTANCE hInstance;
  89. static    HTASK    hTask;
  90.  
  91.  
  92. #pragma argsused
  93. BOOL    CALLBACK _export EnumOldApp(HWND hThisWnd, LPARAM lParam)
  94. {
  95.     hWndOA = hThisWnd;
  96.     return TRUE;
  97. }
  98.  
  99. HTASK    GetTaskFromInstance(HINSTANCE hInst)
  100. {
  101.     TASKENTRY    te;
  102.  
  103.     te.dwSize = sizeof(TASKENTRY);
  104.     TaskFirst(&te);
  105.     do
  106.     {
  107.         if (te.hInst == hInst)
  108.             return te.hTask;
  109.     } while (TaskNext(&te));
  110.     return 0;
  111. }
  112.  
  113. HINSTANCE GetInstanceFromTask(HTASK hTask)
  114. {
  115.     TASKENTRY    te;
  116.  
  117.     te.dwSize = sizeof(TASKENTRY);
  118.     TaskFirst(&te);
  119.     do
  120.     {
  121.         if (te.hTask == hTask)
  122.             return te.hInst;
  123.     } while (TaskNext(&te));
  124.     return 0;
  125. }
  126.  
  127.  
  128. char    *BaseName(char *File)
  129. {
  130.     char    *c1;
  131.     char    *c2;
  132.  
  133.     c1 = strrchr(File, '\\');
  134.     c2 = strrchr(File, '/');
  135.     if (c1 || c2)
  136.     {
  137.         if (c1 > c2)
  138.             return c1+1;
  139.         else
  140.             return c2+1;
  141.     }
  142.     return File;
  143. }
  144.  
  145. #define    MAXTASKS    20
  146.  
  147. char    WhiteSpace[] = " \t";
  148. char    EmptyString[] = "";
  149.  
  150. struct    TaskInfo
  151. {
  152.     HTASK    hTask;
  153.     WORD    wStatus;
  154. };
  155.  
  156. #define    EF_BATCH    0x0001
  157.  
  158. struct    ExtTypes
  159. {
  160.     char    Ext[4];
  161.     char    Prog[13];
  162.     int    Exists;
  163.     int    Flags;
  164. } Extensions[80] =
  165. {
  166.     "EXE",    "",        0,    0,
  167.     "COM",    "",        0,    0,
  168.     "TSH",    "*",        0,    EF_BATCH,
  169.     "BAT",    "",        0,    0,
  170.     "PIF",    "",        0,    0,
  171.     "",    "",        0,    0
  172. };
  173.  
  174. BOOL    NewDead = FALSE;
  175.  
  176. struct    TaskInfo    Tasks[MAXTASKS];
  177.  
  178. void    FlushMessages(void)
  179. {
  180.     MSG    msg;
  181.  
  182.     while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
  183.     {
  184.         TranslateMessage(&msg);
  185.         DispatchMessage(&msg);
  186.     }
  187. }
  188.  
  189.  
  190. int    cmdnum = 0;
  191.  
  192. char    *prompt_names[3] = { "PS1", "PS2", "PS3" };
  193.  
  194. void    PutFormat(char *buffer, char const *format)
  195. {
  196.     char    *c;
  197.     char    const *tmp;
  198.     char    varname[20];
  199.  
  200.     c = buffer;
  201.     for (;*format;format++)
  202.     {
  203.         switch(*format)
  204.         {
  205.         case '!':
  206.             sprintf(c, "%d", cmdnum);
  207.             c+=strlen(c);
  208.             break;
  209.         case '~':
  210.             strcpy(c, pwd());
  211.             c+=strlen(c);
  212.             break;
  213.         case '$':
  214.             if (format[1]!='{')
  215.                 break;
  216.             tmp = ++format;
  217.             while (*format && *format != '}')
  218.                 format++;
  219.             if (!*format)
  220.             {
  221.                 format--;
  222.                 break;
  223.             }
  224.             strncpy(varname, tmp, format-tmp);
  225.             varname[format-tmp] = '\0';
  226.             if ((tmp = getenv(varname)) != 0)
  227.             {
  228.                 strcpy(c, tmp);
  229.                 c+=strlen(c);
  230.             }
  231.             break;
  232.         default:
  233.             *c++ = *format;
  234.             break;
  235.         }
  236.     }
  237.     *c = '\0';
  238. }
  239.  
  240.  
  241. void    show_prompt(int number)
  242. {
  243.     char    *format;
  244.     char    buffer[160];
  245.     char    *c;
  246.     char    *tmp;
  247.     char    varname[20];
  248.     struct    time timeval;
  249.     long    dateval;
  250.     struct  tm *gmt;
  251.  
  252.     c = buffer;
  253.     if ((format = getenv(prompt_names[number])) != 0)
  254.     {
  255.         PutFormat(buffer, format);
  256.     }
  257.     else
  258.     {
  259.         format = getenv("PROMPT");
  260.         for (;*format;format++)
  261.         {
  262.             if (*format == '$')
  263.             {
  264.                 switch(*++format)
  265.                 {
  266.                 case 'p':
  267.                     strcpy(c, pwd());
  268.                     c+=strlen(c);
  269.                     break;
  270.                 case 'q':
  271.                     *c++ = '=';
  272.                     break;
  273.                 case '$':
  274.                     *c++ = '$';
  275.                     break;
  276.                 case 't':
  277.                     gettime(&timeval);
  278.                     sprintf(c, "%02d:%02d:%02d.%02d",
  279.                         timeval.ti_hour,
  280.                         timeval.ti_min,
  281.                         timeval.ti_sec,
  282.                         timeval.ti_hund);
  283.                     c += strlen(c);
  284.                     break;
  285.                 case 'd':
  286.                     time(&dateval);
  287.                     gmt = gmtime(&dateval);
  288.                     sprintf(c, "%3.3s %02d-%02d-%04d",
  289.                         Days[gmt->tm_wday],
  290.                         gmt->tm_mon+1,
  291.                         gmt->tm_mday,
  292.                         gmt->tm_year+1900);
  293.                     c += strlen(c);
  294.                     break;
  295.                 case 'v':
  296.                     sprintf(c, "MS-DOS Version %d.%d", _osmajor, _osminor);
  297.                     c += strlen(c);
  298.                     break;
  299.                 case 'l':
  300.                     *c++ = '<';
  301.                     break;
  302.                 case 'g':
  303.                     *c++ = '>';
  304.                     break;
  305.                 case 's':
  306.                     *c++ = ';';
  307.                     break;
  308.                 case 'c':
  309.                     *c++ = ':';
  310.                     break;
  311.                 case 'r':
  312.                     *c++ = '\r';
  313.                     break;
  314.                 case '_':
  315.                     *c++ = '\n';
  316.                     break;
  317.                 case 'n':
  318.                     *c++ = 'A' + getdisk();
  319.                     break;
  320.                 case 'b':
  321.                     *c++ = '|';
  322.                     break;
  323.                 case 'e':
  324.                     *c++ = '\033';
  325.                     break;
  326.                 case 'h':
  327.                     *c++ = '\b';
  328.                     break;
  329.                 case '!':
  330.                     sprintf(c, "%d", cmdnum);
  331.                     c+=strlen(c);
  332.                     break;
  333.                 case '\0':
  334.                     format--;
  335.                 }
  336.             }
  337.             else
  338.                 (*c++ = *format);
  339.         }
  340.         *c = '\0';
  341.     }
  342.     printf("%s", buffer);
  343.     if (hWnd && (format = getenv("WS1")) != 0)
  344.     {
  345.         PutFormat(buffer, format);
  346.         SetWindowText(hWnd, buffer);
  347.     }
  348. }
  349.  
  350.  
  351. #pragma argsused
  352. main(int argc, char **argv)
  353. {
  354.      int    i;
  355.     FILE    *fp;
  356.     long    wstatus;
  357.     short    pid;
  358.  
  359.     hTask = GetCurrentTask();
  360.     hInstance = GetInstanceFromTask(hTask);
  361.     for (i = 0; i<MAXTASKS; i++)
  362.         Tasks[i].hTask = 0;
  363.     if (tkern_is_device(0, "window"))
  364.         hWnd = (HWND) ioctl(0, WIOCGETHANDLE);
  365.     
  366.     if ((fp = fopen("C:\\AUTOEXEC.TSH", "r")) != 0)
  367.     {
  368.         while (fgets(buf, 2048, fp))
  369.         {
  370.             buf[strlen(buf)-1] = '\0';
  371.             parse_command(buf);
  372.         }
  373.         fclose(fp);
  374.     }
  375.     while(1)
  376.     {
  377.         ++cmdnum;
  378.         while ((pid = waitpid(0, &wstatus , WNOHANG)) > 0)
  379.         {
  380.             if (WIFEXITED(wstatus))
  381.                 printf("%d - Exit %d\n",
  382.                     (int) pid,
  383.                     (int) WEXITSTATUS(wstatus));
  384.             else if (WIFSTOPPED(wstatus))
  385.                 printf("%d - Stopped\n",
  386.                     (int) pid);
  387.             else
  388.                 printf("%d - Terminated (Signal %d)\n",
  389.                     (int) pid,
  390.                     (int) WTERMSIG(wstatus));
  391.         }
  392.         show_prompt(0);
  393.         if (!gets(buf))
  394.             break;
  395.         parse_command(buf);
  396.     }
  397.     return 0;
  398. }
  399.  
  400. #pragma argsused
  401. char *pwd(void)
  402. {
  403.     static char buf[256];
  404.     char *s;
  405.  
  406.     return ((s = getcwd(buf, 255)) != 0) ? s : "invalid";
  407. }
  408.  
  409. #pragma argsused
  410. int do_pwd(int argc, char **argv)
  411. {
  412.     printf("Current directory is %s\n", pwd());
  413.     return 0;
  414. }
  415.  
  416. int do_chdrive(char *s)
  417. {
  418.     if (islower(*s))
  419.         *s=toupper(*s);
  420.     if (s[1] == ':')
  421.     {
  422.         setdisk(s[0] - 'A');
  423.         return 0;
  424.     }
  425.     else
  426.     {
  427.         return 1;
  428.     }
  429. }
  430.  
  431. int do_cd(int argc, char **argv)
  432. {
  433.     if (argc != 1)
  434.     {
  435.         printf("Usage: cd directory\n");
  436.         return 1;
  437.     }
  438.     if (argv[0][1] == ':')
  439.     {
  440.         // allow drives in here too
  441.         if (do_chdrive(argv[0]))
  442.             return 2;
  443.         argv[0] += 2;
  444.     }
  445.     if (*argv[0] && chdir(argv[0]))
  446.     {
  447.         printf("File not found\n");
  448.         return 3;
  449.     }
  450.     else
  451.         return 0;
  452. }
  453.  
  454. #define    DF_LONG    1
  455. #define    DF_SIZE    2
  456. #define    DF_ALL    4
  457. #define    DF_PC    8
  458. #define    DF_DIRONLY 16
  459. #define    DF_SPC 32
  460. #define    DF_RECUR 64
  461. #define    DF_DOS 128
  462.  
  463. void show_filename(char *directory, struct find_t *pinfo, unsigned Flags, unsigned FileNo)
  464. {
  465.     struct stat sbuf;
  466.     char    attributes[8];
  467.     char *c, *c2;
  468.     struct    tm *modtime;
  469.     char    path[256];
  470.     char    specialc;
  471.  
  472.     strcpy(path, directory);
  473.     if (path[0] && path[strlen(path) - 1] != '\\')
  474.         strcat(path, "\\");
  475.     strcat(path, pinfo->name);
  476.     stat(path, &sbuf);
  477.     c=attributes;
  478.     specialc = ' ';
  479.     switch(sbuf.st_mode&S_IFMT)
  480.     {
  481.     case S_IFDIR:
  482.         *c++='d';
  483.         specialc = '/';
  484.         break;
  485.     case S_IFIFO:
  486.         *c++='p';
  487.         break;
  488.     case S_IFCHR:
  489.         *c++='c';
  490.         break;
  491.     case S_IFBLK:
  492.         *c++='b';
  493.         break;
  494.     default:
  495.         *c++='-';
  496.         break;
  497.     }
  498.     modtime = localtime(&sbuf.st_mtime);
  499.     *c++=(sbuf.st_mode&S_IREAD)?'r':'-';
  500.     if ((sbuf.st_mode&S_IFMT) == S_IFDIR)
  501.         *c++ = 'w';
  502.     else
  503.         *c++=(sbuf.st_mode&S_IWRITE)?'w':'-';
  504.     if ((c2 = strrchr(pinfo->name, '.')) != 0 &&
  505.         !(strcmp(c2+1, "EXE") &&
  506.           strcmp(c2+1, "COM") &&
  507.           strcmp(c2+1, "BAT") &&
  508.           strcmp(c2+1, "DIR") &&
  509.           strcmp(c2+1, "TEX") &&
  510.           strcmp(c2+1, "TCO") &&
  511.           strcmp(c2+1, "TSH")))
  512.     {
  513.             specialc = '*';
  514.         *c++ = 'x';
  515.     }
  516.     else
  517.         *c++=(sbuf.st_mode&S_IEXEC)?'x':'-';
  518.     *c++=(pinfo->attrib & _A_SYSTEM)?'s':'-';
  519.     *c++=(pinfo->attrib & _A_HIDDEN)?'h':'-';
  520.     *c++=(pinfo->attrib & _A_ARCH)?'a':'-';
  521.     *c='\0';
  522.     if (!(sbuf.st_mode&S_IFDIR))
  523.         for (c=pinfo->name; *c; c++)
  524.             if (isupper(*c))
  525.                 *c=tolower(*c);
  526.     if (!(Flags & DF_PC))
  527.         specialc = ' ';
  528.     if (Flags & DF_DOS)
  529.     {
  530.             if (sbuf.st_mode&S_IFDIR)
  531.             {
  532.                 printf("%-12s <DIR>     %2d-%02d-%02d   %02d:%02d%c\n",
  533.                     pinfo->name, modtime->tm_mon+1, modtime->tm_mday,
  534.                     modtime->tm_year,
  535.                     (modtime->tm_hour==0)?12:(
  536.                 (modtime->tm_hour<12)?modtime->tm_hour:(modtime->tm_hour-12)),
  537.                 modtime->tm_min, (modtime->tm_hour<12)?'a':'p');
  538.             }
  539.             else
  540.             {
  541.                 printf("%-12s %9ld %2d-%02d-%02d   %02d:%02d%c\n",
  542.                 pinfo->name, pinfo->size,
  543.                 modtime->tm_mon+1, modtime->tm_mday,
  544.                     modtime->tm_year,
  545.                     (modtime->tm_hour==0)?12:(
  546.                 (modtime->tm_hour<12)?modtime->tm_hour:(modtime->tm_hour-12)),
  547.                 modtime->tm_min, (modtime->tm_hour<12)?'a':'p');
  548.         }
  549.     }
  550.     else if (Flags & DF_LONG)
  551.     {
  552.         printf(" %s %8ld %2d-%3.3s-%2.2d %02d:%02d %s%c\n", 
  553.             attributes, pinfo->size,
  554.             modtime->tm_mday, Months[modtime->tm_mon], modtime->tm_year,
  555.             modtime->tm_hour, modtime->tm_min, pinfo->name, specialc);
  556.     }
  557.     else
  558.     {
  559.         printf("%s%c%*.*s", pinfo->name, specialc,
  560.             14-strlen(pinfo->name), 14-strlen(pinfo->name), "                ");
  561.         if (FileNo%5 == 4)
  562.             putchar('\n');
  563.     }
  564. }
  565.  
  566. void    list_file(char *name, unsigned Flags)
  567. {
  568.     char dirname[80];
  569.     char wildcard[80];
  570.     unsigned attrib;
  571.     unsigned files;
  572.     unsigned long bytes;
  573.     struct find_t info;
  574.     struct stat sbuf;
  575.     
  576.     strcpy(dirname, name);
  577.     *BaseName(dirname) = '\0';
  578.     strcpy(wildcard, name);
  579.     if (strlen(wildcard) == 2 && wildcard[1] == ':')
  580.             strcat(wildcard, ".");
  581.     attrib = _A_NORMAL | _A_SUBDIR | _A_RDONLY;
  582.     if (Flags & DF_ALL)
  583.             attrib |= _A_SYSTEM | _A_HIDDEN;
  584.     if (!(Flags&DF_DIRONLY) &&
  585.             !strchr(wildcard, '?') &&
  586.             !strchr(wildcard, '*') &&
  587.         stat(wildcard, &sbuf) != -1 &&
  588.         (sbuf.st_mode & S_IFMT) == S_IFDIR)
  589.     {
  590.             if (wildcard[strlen(wildcard)-1] != '\\')
  591.             {
  592.                 strcat(wildcard, "\\");
  593.             strcpy(dirname, wildcard);
  594.         }
  595.         strcat(wildcard, "*.*");
  596.     }
  597.     files = 0;
  598.     if (_dos_findfirst(wildcard, attrib, &info) != 0)
  599.     {
  600.         printf("%s: File Not Found\n", wildcard);
  601.         return;
  602.     }
  603.     files = 0;
  604.     bytes = 0;
  605.     do
  606.     {
  607.         if (*info.name == '.' && !(Flags&DF_SPC))
  608.                 continue;
  609.            show_filename(dirname, &info, Flags, files);
  610.             files++;
  611.            bytes += info.size;
  612.     } while (_dos_findnext(&info) == 0);
  613.     if (!(Flags & (DF_DOS | DF_LONG)) && (files % 5))
  614.         putchar('\n');
  615.     printf("%5u File(s)\t%lu bytes\n", files, bytes);
  616.     return;
  617. }
  618.  
  619.  
  620. int do_std_dir(int argc, char **argv, unsigned Flags)
  621. {
  622.     struct find_t info;
  623.     unsigned long bytes;
  624.     unsigned attrib, files;
  625.     char *arg;
  626.     struct stat sbuf;
  627.  
  628.     while (argc && **argv == '-')
  629.     {
  630.         argc--;
  631.         arg = *argv++;
  632.            while (*++arg)
  633.             {
  634.                 switch(*arg)
  635.                 {
  636.                 case 'l':
  637.                     Flags |= DF_LONG;
  638.                     break;
  639.                 case 'a':
  640.                     Flags |= DF_ALL | DF_SPC;
  641.                     break;
  642.                 case 'A':
  643.                     Flags |= DF_ALL;
  644.                     break;
  645.                 case 's':
  646.                 Flags |= DF_SIZE;
  647.                     break;
  648.             case 'C':
  649.                     break; /* No op */
  650.                case 'd':
  651.                     Flags |= DF_DIRONLY;
  652.                     break;
  653.                 case 'F':
  654.                     Flags |= DF_PC;
  655.                     break;
  656.                 case 'R':
  657.                     Flags |= DF_RECUR;
  658.                     break;
  659.                 case 'D':
  660.                     Flags |= DF_DOS;
  661.                     break;
  662.             case 'W':
  663.             case 'w':
  664.                 Flags &= ~DF_DOS;
  665.             default:
  666.                 fprintf(stderr, "Usage: ls [-laAsCdFRDwW] [directories]\n");
  667.                 return 1;
  668.                 }
  669.             }
  670.         }
  671.     if (argc)
  672.         {
  673.         while (argc--)
  674.             list_file(*argv++, Flags);
  675.         }
  676.     else
  677.         list_file(".", Flags);
  678.     return 0;
  679. }
  680.  
  681. int do_dir(int argc, char **argv)
  682. {
  683.     return do_std_dir(argc, argv, 0);
  684. }
  685.  
  686. int do_dos_dir(int argc, char **argv)
  687. {
  688.     return do_std_dir(argc, argv, DF_DOS);
  689. }
  690.  
  691. int do_df(int argc, char **argv)
  692. {
  693.     struct    diskfree_t dtable;
  694.     char    drive;
  695.     long    nKbytes;
  696.  
  697.     printf("Drive      CSize      Total       Free      KB Free  %%Used\n");
  698.     if (argc)
  699.     {
  700.         while (argc--)
  701.         {
  702.             if (!_dos_getdiskfree(toupper(*argv[0]) - '@', &dtable))
  703.             {
  704.                 nKbytes = (long) dtable.avail_clusters *
  705.                       (long) dtable.sectors_per_cluster *
  706.                       (long) dtable.bytes_per_sector /
  707.                       1024l;
  708.                 printf("%c:    %7u    %7u    %7u %9lu  %5.1f\n",
  709.                     toupper(*argv[0]),
  710.                     dtable.sectors_per_cluster * dtable.bytes_per_sector,
  711.                     dtable.total_clusters,
  712.                     dtable.avail_clusters,
  713.                     nKbytes,
  714.                     ((float) dtable.total_clusters - dtable.avail_clusters) /
  715.                         dtable.total_clusters * 100.0);
  716.             }
  717.             else
  718.             {
  719.                 printf("Invalid drive specification\n");
  720.             }
  721.             argv++;
  722.         }
  723.         return 0;
  724.     }
  725.     for (drive = 3; drive < 26; drive++)
  726.     {
  727.         if (_dos_getdiskfree(drive, &dtable))
  728.             continue;
  729.         nKbytes = (long) dtable.avail_clusters *
  730.               (long) dtable.sectors_per_cluster *
  731.               (long) dtable.bytes_per_sector /
  732.                   1024l;
  733.         printf("%c:    %7u    %7u    %7u %9lu  %5.1f\n",
  734.             (char) ('@' + drive),
  735.             dtable.sectors_per_cluster * dtable.bytes_per_sector,
  736.             dtable.total_clusters,
  737.             dtable.avail_clusters,
  738.             nKbytes,
  739.             (float) (((float) dtable.total_clusters - dtable.avail_clusters) /
  740.                 dtable.total_clusters * 100.0));
  741.     }
  742.     return 0;
  743. }
  744.  
  745.  
  746.  
  747. char *expand_wildcards(char *s)
  748. {
  749.     static    struct find_t info;
  750.     char wildcard[80];
  751.     static char directory[256];
  752.     static char filename[256];
  753.     unsigned attrib;
  754.     char *c1, *c2;
  755.  
  756.     if (s)
  757.     {
  758.         strcpy(wildcard, s);
  759.         strcpy(directory, wildcard);
  760.             if ((c1 = strrchr(directory, '/')) != 0 ||
  761.             (c2 = strrchr(directory, '\\')) != 0)
  762.             {
  763.             if (c1 > c2)
  764.                 c1[1] = '\0';
  765.             else
  766.                 c2[1] = '\0';
  767.         }
  768.         else
  769.             directory[0] = '\0';
  770.         if (! strchr(wildcard, '.'))
  771.             strcat(wildcard, "*.*");
  772.         attrib = _A_NORMAL | _A_SUBDIR | _A_RDONLY;
  773.         if (_dos_findfirst(wildcard, attrib, &info) != 0)
  774.             return NULL;
  775.         while (!strcmp(info.name, ".") || !strcmp(info.name, ".."))
  776.             if (_dos_findnext(&info))
  777.                 return NULL;
  778.     }
  779.     else
  780.     {
  781.         if (_dos_findnext(&info) != 0)
  782.             return NULL;
  783.     }
  784.     strcpy(filename, directory);
  785.     strcat(filename, info.name);
  786.     return filename;
  787. }
  788.  
  789.  
  790. char *FindExe(char *Path, char *Name, int *batch)
  791. {
  792.     static char ExecLine[256];
  793.     struct find_t info;
  794.     char wildcard[160];
  795.     int    i;
  796.     unsigned attrib;
  797.     char *Ext;
  798.     int r;
  799.     int HasExt = 0;
  800.  
  801.     *batch = 0;
  802.     for (i=0; *Extensions[i].Ext; i++)
  803.         Extensions[i].Exists = 0;
  804.     if (Path)
  805.     {
  806.         strcpy(wildcard, Path);
  807.         strcat(wildcard, "\\");
  808.     }
  809.     else
  810.         *wildcard = '\0';
  811.     strcat(wildcard, Name);
  812.     if (! strchr(Name, '.'))
  813.         strcat(wildcard, ".*");
  814.     else
  815.         HasExt = 1;
  816.     attrib = _A_NORMAL | _A_SUBDIR | _A_RDONLY;
  817.     for (r = _dos_findfirst(wildcard, attrib, &info); !r; r = _dos_findnext(&info))
  818.     {
  819.         if ((Ext = strchr(info.name, '.')) == 0)
  820.             continue;
  821.         Ext++;
  822.         for (i = 0; *Extensions[i].Ext; i++)
  823.         {
  824.             if (!stricmp(Extensions[i].Ext, Ext))
  825.             {
  826.                 Extensions[i].Exists = 1;
  827.                 break;
  828.             }
  829.         }
  830.         }
  831.     for (i = 0; *Extensions[i].Ext; i++)
  832.     {
  833.         if (Extensions[i].Exists)
  834.         {
  835.             if (*Extensions[i].Prog == '*')
  836.             {
  837.                 *batch = 1;
  838.                 *ExecLine = '\0';
  839.             }
  840.             else if (*Extensions[i].Prog)
  841.             {
  842.                 strcpy(ExecLine, Extensions[i].Prog);
  843.                 strcat(ExecLine, " ");
  844.             }
  845.             else
  846.                 *ExecLine = '\0';
  847.             strcat(ExecLine, Name);
  848.             if (!HasExt)
  849.             {
  850.                 strcat(ExecLine, ".");
  851.                 strcat(ExecLine, Extensions[i].Ext);
  852.             }
  853.             return ExecLine;
  854.         }
  855.     }
  856.     return NULL;
  857. }
  858.  
  859. char *FindPath(char *s, int *IsBatch)
  860. {
  861.     char    PathList[256];
  862.     char    *ExeName;
  863.     char    *PathElement;
  864.  
  865.     if (strchr(s, '/') || strchr(s, '\\'))
  866.     {
  867.         return FindExe(NULL, s, IsBatch);
  868.     }
  869.     strcpy(PathList, ".;");
  870.     strcat(PathList, getenv("PATH"));
  871.     for (PathElement = strtok(PathList, ";"); PathElement; PathElement = strtok(NULL, ";"))
  872.         if ((ExeName = FindExe(PathElement, s, IsBatch)) != 0)
  873.             return ExeName;
  874.     return NULL;
  875. }
  876.  
  877.  
  878. int do_activate(int argc, char **argv)
  879. {
  880.     HWND hWnd;
  881.  
  882.     while (argc--)
  883.     {
  884.         hWnd = FindWindow(NULL, *argv);
  885.         if (hWnd)
  886.         {
  887.             argv++;
  888.             BringWindowToTop(hWnd);
  889.             if (IsIconic(hWnd))
  890.                 ShowWindow(hWnd, SW_RESTORE);
  891.         }
  892.         else
  893.         {
  894.             fprintf(stderr, "%s: Window not found\n", argv);
  895.             return 1;
  896.         }
  897.     }
  898.     return 0;
  899. }
  900.  
  901. struct    alias
  902. {
  903.     struct    alias *next;
  904.     char    *name;
  905.     char    *text;
  906.     int    inuse;
  907. };
  908.  
  909. struct    alias    *alias_list = NULL;
  910.  
  911. int do_alias(int argc, char **argv)
  912. {
  913.     char    *c;
  914.     struct    alias *Alias;
  915.     int    i;
  916.     int    len;
  917.  
  918.     if (argc)
  919.     {
  920.         if (argc > 1)
  921.         {
  922.             for (len = 0, i = 1; i < argc; i++)
  923.                 len += strlen(argv[i]);
  924.             len += argc - 1;
  925.             Alias = malloc(sizeof(struct alias));
  926.             Alias->name = malloc(strlen(argv[0])+1);
  927.             Alias->text = malloc(len);
  928.             strcpy(Alias->name, argv[0]);
  929.             strcpy(Alias->text, argv[1]);
  930.             for (i = 2; i < argc; i++)
  931.             {
  932.                 strcat(Alias->text, " ");
  933.                 strcat(Alias->text, argv[i]);
  934.             }
  935.             Alias->inuse = 0;
  936.             Alias->next = alias_list;
  937.             alias_list = Alias;
  938.         }
  939.         else
  940.         {
  941.             for (Alias = alias_list; Alias!=NULL; Alias = Alias->next)
  942.             {
  943.                 if (!strcmp(Alias->name, argv[0]))
  944.                 {
  945.                     printf("%-10s %s\n", argv[0], Alias->text);
  946.                     return 0;
  947.                 }
  948.             }
  949.             fprintf(stderr, "No such alias: %s\n", argv[0]);
  950.             return 1;
  951.         }
  952.     }
  953.     else
  954.     {
  955.         for (Alias = alias_list; Alias; Alias = Alias->next)
  956.             printf("%-10s %s\n", Alias->name, Alias->text);
  957.     }
  958.     return 0;
  959. }
  960.  
  961. int    do_set(int argc, char **argv)
  962. {
  963.     char    *word;
  964.     char    *value, envvar[160];
  965.     char    *putable;
  966.     int    i;
  967.     char    **current;
  968.  
  969.     if (!argc)
  970.     {
  971.         for (current = environ; *current; current++)
  972.             printf("%s\n", *current);
  973.         return 0;
  974.     }
  975.     if (argc > 1)
  976.     {
  977.         sprintf(envvar, "%s=%s", argv[0], argv[1]);
  978.         for (i = 2; i < argc; i++)
  979.         {
  980.             strcat(envvar, " ");
  981.             strcat(envvar, argv[i]);
  982.         }
  983.         putable = malloc(strlen(envvar)+1);
  984.         strcpy(putable, envvar);
  985.         if (putenv(putable))
  986.         {
  987.             fprintf(stderr, "%s: %s\n", putable, sys_errlist[errno]);
  988.             free(putable);
  989.         }
  990.     }
  991.     else
  992.     {
  993.         if ((value = getenv(argv[0])) != 0)
  994.         {
  995.             printf("%s=%s\n", argv[0], value);
  996.         }
  997.         else
  998.         {
  999.             printf("No value for %s\n", argv[0]);
  1000.             return 1;
  1001.         }
  1002.     }
  1003.     return 0;
  1004. }
  1005.  
  1006. int    do_mkdir(int argc, char **argv)
  1007. {
  1008.     if (!argc)
  1009.     {
  1010.         fprintf(stderr, "Must specify a directory for mkdir\n");
  1011.         return 0;
  1012.     }
  1013.     while (argc--)
  1014.     {
  1015.         if (mkdir(*argv)==-1)
  1016.         {
  1017.             fprintf(stderr, "%s: %s\n", argv[0], sys_errlist[errno]);
  1018.             return 1;
  1019.         }
  1020.         argv++;
  1021.     }
  1022.     return 0;
  1023. }
  1024.  
  1025. int    do_rmdir(int argc, char **argv)
  1026. {
  1027.     if (!argc)
  1028.     {
  1029.         printf("Must specify a directory for rmdir\n");
  1030.         return 1;
  1031.     }
  1032.     while (argc--)
  1033.     {
  1034.         if (rmdir(*argv)==-1)
  1035.         {
  1036.             fprintf(stderr, "%s: %s\n", argv[0], sys_errlist[errno]);
  1037.             return 1;
  1038.         }
  1039.         argv++;
  1040.     }
  1041.     return 0;
  1042. }
  1043.  
  1044.  
  1045. int    do_del(int argc, char **argv)
  1046. {
  1047.     int    files;
  1048.     char    *sfile;
  1049.     int    error;
  1050.  
  1051.     if (!argc)
  1052.     {
  1053.         printf("Must specify files for del\n");
  1054.         return 1;
  1055.     }
  1056.     while (argc--)
  1057.     {
  1058.         for (files = 0, sfile = expand_wildcards(argv[0]);
  1059.             sfile; files++, sfile = expand_wildcards(NULL))
  1060.         {
  1061.             if (unlink(sfile)==-1)
  1062.             {
  1063.                 fprintf(stderr, "%s: %s\n", sfile, sys_errlist[errno]);
  1064.                 error = 1;
  1065.             }
  1066.         }
  1067.         if (!files)
  1068.         {
  1069.             fprintf(stderr, "%s: file not found\n", argv[0]);
  1070.             error = 1;
  1071.         }
  1072.         argv++;
  1073.     }
  1074.     return error;
  1075. }
  1076.  
  1077. int    do_type(int argc, char **argv)
  1078. {
  1079.     int    files;
  1080.     char    *sfile;
  1081.     FILE    *fp;
  1082.     char    Buffer[512];
  1083.     int    nread;
  1084.     int    error = 0;
  1085.  
  1086.     if (!argc)
  1087.     {
  1088.         fprintf(stderr, "Must specify files for type\n");
  1089.         return 1;
  1090.     }
  1091.     while (argc--)
  1092.     {
  1093.         for (files = 0, sfile = expand_wildcards(argv[0]);
  1094.             sfile; files++, sfile = expand_wildcards(NULL))
  1095.         {
  1096.             if ((fp = fopen(sfile, "r")) == NULL)
  1097.             {
  1098.                 fprintf(stderr, "%s: %s\n", sfile, sys_errlist[errno]);
  1099.                 error = 1;
  1100.                 continue;
  1101.             }
  1102.             while ((nread = fread(Buffer, 1, 512, fp)) > 0)
  1103.                 fwrite(Buffer, 1, nread, stdout);
  1104.             fclose(fp);
  1105.         }
  1106.         if (!files)
  1107.         {
  1108.             fprintf(stderr, "%s: file not found\n", argv[0]);
  1109.             error = 1;
  1110.         }
  1111.         argv++;
  1112.     }
  1113.     return error;
  1114. }
  1115.  
  1116. #pragma argsused
  1117. int    do_mem(int argc, char **argv)
  1118. {
  1119.     printf("%ldK free %d%% System Resources free\n",
  1120.         GetFreeSpace(0) / 1024,
  1121.         GetFreeSystemResources(GFSR_SYSTEMRESOURCES));
  1122.     return 0;
  1123. }
  1124.  
  1125. #pragma argsused
  1126. int    do_sysinfo(int argc, char **argv)
  1127. {
  1128.     DWORD    sys_info;
  1129.  
  1130.     sys_info = GetWinFlags();
  1131.  
  1132.     if (sys_info & WF_80x87)
  1133.         printf("Maths Coprocessor Present\n");
  1134.     if (sys_info & WF_CPU286)
  1135.         printf("80286 Processor\n");
  1136.     if (sys_info & WF_CPU386)
  1137.         printf("80386 Processor\n");
  1138.     if (sys_info & WF_CPU486)
  1139.         printf("i486 Processor\n");
  1140.     if (sys_info & WF_ENHANCED)
  1141.         printf("Enhanced Mode\n");
  1142.     if (sys_info & WF_STANDARD)
  1143.         printf("Standard Mode\n");
  1144.     if (sys_info & WF_PAGING)
  1145.         printf("System has paging\n");
  1146.     return 0;
  1147. }
  1148.  
  1149. /*
  1150.  * ps - list all running tasks with useful info. Note that while we are printing,
  1151.  * we may process messages. Once this happens, the task list may be in a new order.
  1152.  * consequently, we must build the list without displaying, and then display the
  1153.  * results from the list.
  1154.  */
  1155.  
  1156. extern    int    tkern_total_zombies(void);
  1157. extern    int    tkern_list_zombies(struct tk_process *, int);
  1158. extern    int    tkern_get_process(HTASK, struct tk_process *);
  1159.  
  1160. #pragma argsused
  1161. int    do_ps(int argc, char **argv)
  1162. {
  1163.     TASKENTRY    te;
  1164.     FARPROC lpfnEnumWndProc;
  1165.     char    TaskName[160];
  1166.     int    nTasks = 0;
  1167.     int    iTask = 0;
  1168.     TASKENTRY    *teList;
  1169.     char    **ppchTaskNames;
  1170.     struct    tk_process *pZombies;
  1171.     struct    tk_process *pProcesses;
  1172.     int    nZombies;
  1173.     int    i;
  1174.  
  1175.     te.dwSize = sizeof(TASKENTRY);
  1176.     printf("  PID  PPID Task  Parent Hinst Events StkSz Command\n");
  1177.        lpfnEnumWndProc = MakeProcInstance((FARPROC) EnumOldApp, hInstance);
  1178.     TaskFirst(&te);
  1179.     do
  1180.     {
  1181.         nTasks++;
  1182.     } while (TaskNext(&te));
  1183.     pProcesses = (struct tk_process *) malloc(sizeof(*pProcesses) * nTasks);
  1184.     nZombies = tkern_total_zombies();
  1185.     if (nZombies)
  1186.     {
  1187.         pZombies = (struct tk_process *) malloc(sizeof(*pZombies) * nZombies);
  1188.         tkern_list_zombies(pZombies, nZombies);
  1189.     }
  1190.     teList = (TASKENTRY *) malloc(sizeof(TASKENTRY) * nTasks);
  1191.     ppchTaskNames = malloc(sizeof(char *) * nTasks);
  1192.     memset(ppchTaskNames, 0, sizeof(char *) * nTasks);
  1193.     TaskFirst(&te);
  1194.     do
  1195.     {
  1196.         teList[iTask] = te;
  1197.         tkern_get_process(te.hTask, &pProcesses[iTask]);
  1198.         strcpy(TaskName, teList[iTask].szModule);
  1199.         if (!strcmp(TaskName, "WINOLDAP"))
  1200.         {
  1201.             hWndOA = 0;
  1202.             EnumTaskWindows(teList[iTask].hTask, (WNDENUMPROC) lpfnEnumWndProc, 0L);
  1203.             if (hWndOA)
  1204.                 GetWindowText(hWndOA, TaskName, 160);
  1205.             ppchTaskNames[iTask] = malloc(strlen(TaskName) + 1);
  1206.             strcpy(ppchTaskNames[iTask], TaskName);
  1207.         }
  1208.         iTask++;
  1209.     } while (TaskNext(&te));
  1210.     for (iTask = 0; iTask < nTasks; iTask++)
  1211.     {
  1212.         printf("%5d %5d %5d %5d  %5d %5d  %4x  %s\n",
  1213.             pProcesses[iTask].pid,
  1214.             pProcesses[iTask].pidParent,
  1215.             teList[iTask].hTask,
  1216.             teList[iTask].hTaskParent,
  1217.             teList[iTask].hInst,
  1218.             teList[iTask].wcEvents,
  1219.             teList[iTask].wStackBottom - teList[iTask].wStackTop,
  1220.             ppchTaskNames[iTask] ? ppchTaskNames[iTask] : teList[iTask].szModule);
  1221.         if (ppchTaskNames[iTask])
  1222.             free(ppchTaskNames[iTask]);
  1223.     }
  1224.     free(ppchTaskNames);
  1225.     free(teList);
  1226.     free(pProcesses);
  1227.     FreeProcInstance(lpfnEnumWndProc);
  1228.     if (nZombies)
  1229.     {
  1230.         for (i = 0; i < nZombies; i++)
  1231.             printf("%5d %5d                                 <defunct>\n",
  1232.                 (int) pZombies[i].pid,
  1233.                 (int) pZombies[i].pidParent);
  1234.         free(pZombies);
  1235.     }
  1236.     return 0;
  1237. }
  1238.  
  1239. int    do_kill(int argc, char **argv)
  1240. {
  1241.     int    signal;
  1242.     char    *flags;
  1243.     int    pid;
  1244.     BOOL    bError = FALSE;
  1245.  
  1246.     if (argc && *argv[0] == '-')
  1247.     {
  1248.         signal = atoi(argv[0]+1);
  1249.         argc--;
  1250.         argv++;
  1251.     }
  1252.     else
  1253.         signal = 14;
  1254.  
  1255.     if (!argc)
  1256.     {
  1257.         printf("Usage: kill [-#] task\n");
  1258.         return 1;
  1259.     }
  1260.     do
  1261.     {
  1262.         pid = atoi(argv[0]);
  1263.         if (kill(pid, signal) == -1)
  1264.             fprintf(stderr, "%d: %s\n", pid, sys_errlist[errno]);
  1265.         argv++;
  1266.     } while (--argc);
  1267.     return bError;
  1268. }
  1269.  
  1270. #pragma argsused
  1271. int    do_date(int argc, char **argv)
  1272. {
  1273.     long tm;
  1274.  
  1275.     time(&tm);
  1276.     printf("%s", ctime(&tm));
  1277.     return 0;
  1278. }
  1279.  
  1280. int    do_mv(int argc, char **argv)
  1281. {
  1282.     char    *dest;
  1283.     struct    stat sbuf;
  1284.     char    TmpBuffer[160];
  1285.     char    *FileStart;
  1286.     char    *sfile;
  1287.     int    files;
  1288.     int    error = 0;
  1289.  
  1290.     if ((argc > 2 && (stat(argv[argc-1], &sbuf) == -1 ||
  1291.               !(sbuf.st_mode & S_IFDIR))) ||
  1292.         argc < 2)
  1293.     {
  1294.         fprintf(stderr, "Usage: mv file1 file2\n    mv files directory\n");
  1295.         return 1;
  1296.     }
  1297.  
  1298.     dest = argv[argc-1];
  1299.     argc--;
  1300.     if (strlen(dest) == 2 && dest[1] == ':')
  1301.     {
  1302.         strcpy(TmpBuffer, dest);
  1303.         strcat(TmpBuffer, ".\\");
  1304.         dest = TmpBuffer;
  1305.         FileStart = TmpBuffer + strlen(TmpBuffer);
  1306.     }
  1307.     else if (stat(dest, &sbuf) != -1 && sbuf.st_mode & S_IFDIR)
  1308.     {
  1309.         strcpy(TmpBuffer, dest);
  1310.         if (TmpBuffer[strlen(TmpBuffer)-1] != '\\')
  1311.             strcat(TmpBuffer, "\\");
  1312.         FileStart = TmpBuffer + strlen(TmpBuffer);
  1313.         dest = TmpBuffer;
  1314.     }
  1315.     else
  1316.         FileStart = NULL;
  1317.     while (argc--)
  1318.     {
  1319.         for (files = 0, sfile = expand_wildcards(argv[0]);
  1320.             sfile; files++, sfile = expand_wildcards(NULL))
  1321.         {
  1322.             if (FileStart)
  1323.                 strcpy(FileStart, BaseName(sfile));
  1324.             if (rename(sfile, dest) == -1)
  1325.             {
  1326.                 fprintf(stderr, "%s: %s\n", sfile, sys_errlist[errno]);
  1327.                 error = 1;
  1328.             }
  1329.         }
  1330.         if (!files)
  1331.         {
  1332.             fprintf(stderr, "%s: File not found\n", argv[0]);
  1333.             error = 1;
  1334.         }
  1335.         argv++;
  1336.     }
  1337.     return error;
  1338. }
  1339.  
  1340. int    do_exit(int argc, char **argv)
  1341. {
  1342.     if (argc)
  1343.         exit(atoi(argv[0]));
  1344.     else
  1345.         exit(0);
  1346.     return -1;
  1347. }
  1348.  
  1349.  
  1350.  
  1351. int    do_copy(int argc, char **argv)
  1352. {
  1353.     char    *dest;
  1354.     struct    stat sbuf;
  1355.     char    TmpBuffer[160];
  1356.     char    Buffer[512];
  1357.     char    *FileStart;
  1358.     char    *sfile;
  1359.     int    files;
  1360.     int    fdin, fdout;
  1361.     int    nread;
  1362.     char    far    *lpchBuffer;
  1363.     HANDLE    hMem;
  1364.     unsigned uDate, uTime;
  1365.     int    error = 0;
  1366.  
  1367.     if ((argc > 2 && (stat(argv[argc-1], &sbuf) == -1 ||
  1368.               !(sbuf.st_mode & S_IFDIR))) ||
  1369.         argc < 2)
  1370.     {
  1371.         fprintf(stderr, "Usage: copy file1 file2\n    copy files directory\n");
  1372.         return 1;
  1373.     }
  1374.  
  1375.     dest = argv[argc-1];
  1376.     argc--;
  1377.     if (strlen(dest) == 2 && dest[1] == ':')
  1378.     {
  1379.         strcpy(TmpBuffer, dest);
  1380.         strcat(TmpBuffer, ".\\");
  1381.         dest = TmpBuffer;
  1382.         FileStart = TmpBuffer + strlen(TmpBuffer);
  1383.     }
  1384.     else if (stat(dest, &sbuf) != -1 && sbuf.st_mode & S_IFDIR)
  1385.     {
  1386.         strcpy(TmpBuffer, dest);
  1387.         if (TmpBuffer[strlen(TmpBuffer)-1] != '\\')
  1388.             strcat(TmpBuffer, "\\");
  1389.         FileStart = TmpBuffer + strlen(TmpBuffer);
  1390.         dest = TmpBuffer;
  1391.     }
  1392.     else
  1393.         FileStart = NULL;
  1394.     hMem = GlobalAlloc(GMEM_FIXED, 32000);
  1395.     lpchBuffer = GlobalLock(hMem);
  1396.     while (argc--)
  1397.     {
  1398.         for (files = 0, sfile = expand_wildcards(argv[0]);
  1399.             sfile; files++, sfile = expand_wildcards(NULL))
  1400.         {
  1401.             if (FileStart)
  1402.                 strcpy(FileStart, BaseName(sfile));
  1403.             if ((fdin = _lopen(sfile, READ)) == -1)
  1404.             {
  1405.                 fprintf(stderr, "Cannot open %s: %s\n", sfile, sys_errlist[errno]);
  1406.                 error = 1;
  1407.                 continue;
  1408.             }
  1409.             if ((fdout = _lcreat(dest, 0)) == -1)
  1410.             {
  1411.                 _lclose(fdin);
  1412.                 fprintf(stderr, "Cannot create %s: %s\n", dest, sys_errlist[errno]);
  1413.                 error = 1;
  1414.                 continue;
  1415.             }
  1416.             while ((nread = _lread(fdin, lpchBuffer, 32000)) != 0)
  1417.                 _lwrite(fdout, lpchBuffer, nread);
  1418.  
  1419.             _dos_getftime(fdin, &uDate, &uTime);
  1420.             _dos_setftime(fdout, uDate, uTime);
  1421.             _lclose(fdin);
  1422.             _lclose(fdout);
  1423.         }
  1424.         if (!files)
  1425.         {
  1426.             fprintf(stderr, "%s: File not found\n", argv[0]);
  1427.             error = 1;
  1428.         }
  1429.         argv++;
  1430.     }
  1431.     GlobalUnlock(hMem);
  1432.     GlobalFree(hMem);
  1433.     return error;
  1434. }
  1435.  
  1436. int do_echo(int argc, char **argv)
  1437. {
  1438.     while (argc--)
  1439.     printf("%s ", *argv++);
  1440.     printf("\n");
  1441.     return 0;
  1442. }
  1443.  
  1444. #pragma argsused
  1445. int
  1446. do_true(int    argc,
  1447.     char    **argv)
  1448. {
  1449.     return 0;
  1450. }
  1451.  
  1452. #pragma argsused
  1453. int
  1454. do_false(int    argc,
  1455.     char    **argv)
  1456. {
  1457.     return 1;
  1458. }
  1459.  
  1460. struct
  1461. {
  1462.     char    *name;
  1463.     int    (*func)(int argc, char **argv);
  1464. } command_list[] = {
  1465.     ":",        do_true,
  1466.     "ACTIVATE",    do_activate,
  1467.     "ALIAS",    do_alias,
  1468.     "CD",        do_cd,
  1469.     "COPY",        do_copy,
  1470.     "DATE",        do_date,
  1471.     "DEL",        do_del,
  1472.     "DF",        do_df,
  1473.     "DIR",        do_dos_dir,
  1474.     "ECHO",        do_echo,
  1475.     "EXIT",        do_exit,
  1476.     "FALSE",    do_false,
  1477.     "KILL",        do_kill,
  1478.     "LS",        do_dir,
  1479.     "MEM",        do_mem,
  1480.     "MKDIR",    do_mkdir,
  1481.     "MV",        do_mv,
  1482.     "PS",        do_ps,
  1483.     "PWD",        do_pwd,
  1484.     "RMDIR",    do_rmdir,
  1485.     "SET",        do_set,
  1486.     "SYSINFO",    do_sysinfo,
  1487.     "TRUE",        do_true,
  1488.     "TYPE",        do_type,
  1489.     0,        0
  1490. };
  1491.  
  1492.  
  1493. #pragma argsused
  1494. int    RunBatch(char *FileName, char **argv, int argc)
  1495. {
  1496.     FILE    *fp;
  1497.     char    buf[2048];
  1498.  
  1499.     if ((fp = fopen(FileName, "r")) == 0)
  1500.     {
  1501.         while (fgets(buf, 2048, fp))
  1502.         {
  1503.             buf[strlen(buf)-1] = '\0';
  1504.             parse_command(buf);
  1505.         }
  1506.         fclose(fp);
  1507.         return 0;
  1508.     }
  1509.     else
  1510.     {
  1511.         printf("%s: %s\n", FileName, sys_errlist[errno]);
  1512.         return -1;
  1513.     }
  1514.  
  1515. }
  1516.  
  1517. int expand_alias(char const *cmd, char const *args, int *retval)
  1518. {
  1519.     char *expanded;
  1520.     struct    alias    *Alias;
  1521.  
  1522.     for (Alias = alias_list; Alias; Alias=Alias->next)
  1523.     {
  1524.         if (!stricmp(Alias->name, cmd))
  1525.         {
  1526.             if (Alias->inuse)
  1527.             {
  1528.                 /* Allow an alias to merely add arguments */
  1529.                 return FALSE;
  1530.             }
  1531.             expanded = malloc(strlen(Alias->text)+
  1532.                     strlen(args)+2);
  1533.             strcpy(expanded, Alias->text);
  1534.             if (args)
  1535.             {
  1536.                 strcat(expanded, " ");
  1537.                 strcat(expanded, args);
  1538.             }
  1539.             Alias->inuse = 1;
  1540.             *retval = parse_command(expanded);
  1541.             Alias->inuse = 0;
  1542.             free(expanded);
  1543.             return TRUE;
  1544.         }
  1545.     }
  1546.     return FALSE;
  1547. }
  1548.  
  1549. int do_command(    char    **orig_args,
  1550.         int    nArgs,
  1551.         BOOL    bWait,
  1552.         struct redirection *ar,
  1553.         int    nRedirections)
  1554. {
  1555.     char **args, **alloc_args;
  1556.     int ret; 
  1557.     int    i;
  1558.     int    iTask;
  1559.     char *PathElement;
  1560.     char *ExeName;
  1561.     char Command[256];
  1562.     HTASK hTask;
  1563.     int    GotTask;
  1564.     int IsBatch;
  1565.     HWND    focus;
  1566.     long    wstatus;
  1567.     int    fdSource[3];
  1568.  
  1569.     if (!nArgs)
  1570.         return 0;    /* Null command always succeeds */
  1571.  
  1572.     args = alloc_args = malloc(sizeof(*args) * (nArgs + 1));
  1573.     memcpy(args, orig_args, sizeof(*args) * (nArgs + 1));
  1574.  
  1575.     /* Check for a drive change directive */
  1576.  
  1577.     if (nArgs == 1 &&
  1578.         (strlen(args[0]) == 2) &&
  1579.         (args[0][1] == ':'))     // Change Drive:
  1580.         return do_chdrive(args[0]);
  1581.  
  1582.     /* Check for builtin commands */
  1583.  
  1584.     for (i = 0; command_list[i].name; i++)
  1585.         if (!stricmp(command_list[i].name, args[0]))
  1586.             return (*command_list[i].func)(nArgs-1, args+1);
  1587.  
  1588.  
  1589.     NewDead = 0;
  1590.     strcpy(tmpbuf, ".;");
  1591.     strcat(tmpbuf, getenv("PATH"));
  1592.     strupr(args[0]);
  1593.     if ((ExeName = FindPath(args[0], &IsBatch)) != 0)
  1594.     {
  1595.         if (IsBatch)
  1596.         {
  1597.             ret = RunBatch(ExeName, args+1, nArgs-1);
  1598.         }
  1599.         else
  1600.         {
  1601.             *Command = 0;
  1602.             while (--nArgs)
  1603.             {
  1604.                 if (*Command)
  1605.                     strcat(Command, " ");
  1606.                 ++args;
  1607.                 if (strchr(*args, ' ') ||
  1608.                     strchr(*args, '\t'))
  1609.                 {
  1610.                     strcat(Command, "\"");
  1611.                     strcat(Command, *args);
  1612.                     strcat(Command, "\"");
  1613.                 }
  1614.                 else
  1615.                     strcat(Command, *args);
  1616.             }
  1617.             for (i = 0; i < nRedirections; i++)
  1618.             {
  1619.                 if (ar[i].fdSource != -1)
  1620.                 {
  1621.                     fdSource[i] = dup(ar[i].fdSource);
  1622.                     if (fdSource[i] == -1)
  1623.                         fprintf(stderr, "%d: %s",
  1624.                             ar[i].fdSource,
  1625.                             sys_errlist[errno]);
  1626.                 }
  1627.                 else
  1628.                 {
  1629.                     fdSource[i] = open(    ar[i].pchFile,
  1630.                                 ar[i].iMode,
  1631.                                 0666);
  1632.                     if (fdSource[i] == -1)
  1633.                         fprintf(stderr, "%s: %s",
  1634.                             ar[i].pchFile,
  1635.                             sys_errlist[errno]);
  1636.                 }
  1637.                 if (fdSource[i] == -1)
  1638.                 {
  1639.                     while (i > 0)
  1640.                         close(fdSource[--i]);
  1641.                     free(alloc_args);
  1642.                     return -1;
  1643.                 }
  1644.             }
  1645.             iTask = fork();
  1646.             switch(iTask)
  1647.             {
  1648.             case 0:
  1649.                 for (i = 0; i < nRedirections; i++)
  1650.                 {
  1651.                     dup2(fdSource[i], ar[i].fd);
  1652.                     close(fdSource[i]);
  1653.                 }
  1654.                 execv_ext(Command, ExeName, orig_args);
  1655.                 break;
  1656.  
  1657.             case -1:
  1658.                 fprintf(stderr, "%s: %s\n", ExeName, sys_errlist[errno]);
  1659.                 ret = -1;
  1660.                 break;
  1661.  
  1662.             default:
  1663.                 if (bWait)
  1664.                 {
  1665.                     waitpid(iTask, &wstatus, 0);
  1666.                     if (WIFEXITED(wstatus))
  1667.                         ret = WEXITSTATUS(wstatus);
  1668.                     else
  1669.                         ret = -1;
  1670.                 }
  1671.                 else
  1672.                 {
  1673.                     ret = 0;
  1674.                 }
  1675.                 break;
  1676.             }
  1677.             for (i = 0; i < nRedirections; i++)
  1678.             {
  1679.                 close(fdSource[i]);
  1680.             }
  1681.         }
  1682.     }
  1683.     else
  1684.     {
  1685.         ret = -2;
  1686.         fprintf(stderr, "%s: File not found\n", args[0]);
  1687.     }
  1688.     free(alloc_args);
  1689.     return ret;
  1690. }
  1691.  
  1692. char    const *FindMatch(char const *buffer, char match)
  1693. {
  1694.     for (buffer++; *buffer; buffer++)
  1695.     {
  1696.         if (*buffer == match)
  1697.             return buffer;
  1698.         if (*buffer == '\\' && buffer[1])
  1699.             buffer++;
  1700.     }
  1701.     return 0;
  1702. }
  1703.  
  1704.  
  1705. BOOL    IsEscapable(char c)
  1706. {
  1707.     return (c == '\\' || c == '\'' || c == '"' ||
  1708.         c == ';' || c == ' ' || c == '\t');
  1709. }
  1710.  
  1711. #define    ARG_CHUNK    64
  1712.  
  1713. #define CALC_SIZE(x) (((x)-1)-((x)-1)%ARG_CHUNK+ARG_CHUNK)
  1714.  
  1715. #pragma argsused
  1716. void    CopyTo(char **arg, char const *data, int chars, int dosubs)
  1717. {
  1718.     int    len;
  1719.     int    size;
  1720.     int    newlen;
  1721.     int    newsize;
  1722.     char    *newarg;
  1723.  
  1724.     if (!*arg)
  1725.     {
  1726.         size = 0;
  1727.         len = 1;
  1728.     }
  1729.     else
  1730.     {
  1731.         len = strlen(*arg) + 1;
  1732.         size = CALC_SIZE(len);
  1733.     }
  1734.     newlen = len + chars;
  1735.     newsize = CALC_SIZE(newlen);
  1736.     if (newsize != size)
  1737.     {
  1738.         newarg = malloc(newsize);
  1739.         if (*arg)
  1740.         {
  1741.             memcpy(newarg, arg, len);
  1742.             free(*arg);
  1743.         }
  1744.         *arg = newarg;
  1745.     }
  1746.     memcpy(*arg + len - 1, data, chars);
  1747.     (*arg)[newlen-1] = '\0';
  1748. }
  1749.  
  1750. void    FreeArgs(char **args, int nArgs)
  1751. {
  1752.     int    i;
  1753.  
  1754.     for (i = 0; i < nArgs; i++)
  1755.     {
  1756.         free(args[i]);
  1757.         args[i] = 0;
  1758.     }
  1759. }
  1760.  
  1761. void    FinishArg(char **arg)
  1762. {
  1763.     int    len;
  1764.     int    size;
  1765.     char    *newarg;
  1766.  
  1767.     len = strlen(*arg) + 1;
  1768.     size = CALC_SIZE(len);
  1769.     if (size == len)
  1770.         return;
  1771.     newarg = malloc(len);
  1772.     memcpy(newarg, *arg, len);
  1773.     free(*arg);
  1774.     *arg = newarg;
  1775. }
  1776.  
  1777. #define    TOKEN_ENDCOMMAND    ((unsigned) 0x8001)
  1778. #define    TOKEN_BGCOMMAND        ((unsigned) 0x8002)
  1779. #define    TOKEN_REDIRFROM        ((unsigned) 0x8003)
  1780. #define    TOKEN_REDIRTO        ((unsigned) 0x8004)
  1781. #define    TOKEN_APPENDTO        ((unsigned) 0x8005)
  1782. #define    TOKEN_FDFROM        ((unsigned) 0x8006)
  1783. #define    TOKEN_FDTO        ((unsigned) 0x8007)
  1784.  
  1785. #define    TOKEN_SPECIAL        ((unsigned) 0x8000)
  1786. #define    TOKEN_ERROR        ((unsigned) 0xFFFF)
  1787. #define    TOKEN_NONE        ((unsigned) 0x0000)
  1788. #define    TOKEN_OK        ((unsigned) 0x0001)
  1789.  
  1790. static    char    const achTokenChars[] =
  1791. { ";&<>" };
  1792.  
  1793. struct token_information
  1794. {
  1795.     char    *pchToken;
  1796.     int    nToken;
  1797. };
  1798.  
  1799. static struct token_information ati[] =
  1800. {
  1801.     { ">&",    TOKEN_FDTO    },
  1802.     { "<&",    TOKEN_FDFROM    },
  1803.     { ">>",    TOKEN_APPENDTO    },
  1804.     { ">",    TOKEN_REDIRTO    },
  1805.     { "<",    TOKEN_REDIRFROM    },
  1806.     { "&",    TOKEN_BGCOMMAND    },
  1807.     { ";",    TOKEN_ENDCOMMAND },
  1808.     { 0,    0        }
  1809. };
  1810.  
  1811. unsigned GetArg(char const    **pchString,
  1812.         char        **arg,
  1813.         BOOL        *bRunOn)
  1814. {
  1815.     int    i;
  1816.     int    nLen;
  1817.     char    const *c;
  1818.     char    const *end;
  1819.  
  1820.     *bRunOn = FALSE;
  1821.     c = *pchString;
  1822.     while (isspace(*c))
  1823.         c++;
  1824.     if (!*c)
  1825.     {
  1826.         *bRunOn = FALSE;
  1827.         return TOKEN_NONE;
  1828.     }
  1829.     if (strchr(achTokenChars, *c))
  1830.     {
  1831.         *bRunOn = FALSE;
  1832.         for (i = 0; ati[i].nToken; i++)
  1833.         {
  1834.             nLen = strlen(ati[i].pchToken);
  1835.             if (!strncmp(ati[i].pchToken, c, nLen))
  1836.             {
  1837.                 *pchString = c + nLen;
  1838.                 return ati[i].nToken;
  1839.             }
  1840.         }
  1841.         /* It is impossible to get here */
  1842.         *(char *) 0 = 0;
  1843.     }
  1844.     for (; *c!='\0'; c++)
  1845.     {
  1846.         if (isspace(*c))
  1847.         {
  1848.             FinishArg(arg);
  1849.             *bRunOn = FALSE;
  1850.             *pchString = c;
  1851.             return TOKEN_OK;
  1852.         }
  1853.         if (strchr(achTokenChars, *c))
  1854.         {
  1855.             *bRunOn = TRUE;
  1856.             FinishArg(arg);
  1857.             *pchString = c;
  1858.             return TOKEN_OK;
  1859.         }
  1860.         switch(*c) 
  1861.         {
  1862.         case '"':
  1863.         case '\'':
  1864.             end = FindMatch(c, *c);
  1865.             if (!end)
  1866.             {
  1867.                 fprintf(stderr, "Unterminated %c\n", *c);
  1868.                 if (*arg)
  1869.                 {
  1870.                     free(*arg);
  1871.                     *arg = 0;
  1872.                 }
  1873.                 return TOKEN_ERROR;
  1874.             }
  1875.             CopyTo(arg, c+1, end - c - 1, (*c == '"'));
  1876.             c = end;    
  1877.             break;
  1878.  
  1879.         case '\\':
  1880.             if (IsEscapable(c[1]))
  1881.             {
  1882.                 CopyTo(arg, ++c, 1, 0);
  1883.                 break;
  1884.             }
  1885.         default:
  1886.             CopyTo(arg, c, 1, 0);
  1887.             break;
  1888.         }
  1889.     }
  1890.     *bRunOn = FALSE;
  1891.     *pchString = c;
  1892.     FinishArg(arg);
  1893.     return TOKEN_OK;
  1894. }
  1895.  
  1896. void    free_redirections(    struct redirection *ar,
  1897.                 int    nRedirections)
  1898. {
  1899.     int    i;
  1900.  
  1901.     for (i = 0; i < nRedirections; i++)
  1902.     {
  1903.         if (ar[i].pchFile)
  1904.             free(ar[i].pchFile);
  1905.     }
  1906. }
  1907.  
  1908. int    parse_command(    char    const *pchCmd)
  1909. {
  1910.     char *c, *c2, *end;
  1911.     char    **args;
  1912.     char    *pchArg;
  1913.     int    nUsed;
  1914.     int    fdNow;
  1915.     int    i;
  1916.     int    retval;
  1917.     struct redirection ar[3];
  1918.     int    nRedirections = 0;
  1919.     unsigned nToken, nFileToken;
  1920.     BOOL    bRunOn = FALSE;
  1921.     BOOL    bLastRunOn;
  1922.     BOOL    bNonDigit;
  1923.     int    nFile;
  1924.  
  1925.     args = malloc(50 * sizeof(char *));
  1926.     memset(args, 0, sizeof(*args) * 50);
  1927.     nUsed = 0;
  1928.     while(1)
  1929.     {
  1930.         bLastRunOn = bRunOn;
  1931.         pchArg = 0;
  1932.         nToken = GetArg(&pchCmd, &pchArg, &bRunOn);
  1933.         switch (nToken)
  1934.         {
  1935.         case TOKEN_NONE:
  1936.         case TOKEN_ENDCOMMAND:
  1937.         case TOKEN_BGCOMMAND:
  1938.             if (nUsed)
  1939.             {
  1940.                 retval = do_command(args, nUsed,
  1941.                         (nToken == TOKEN_BGCOMMAND) ? FALSE : TRUE,
  1942.                         ar, nRedirections);
  1943.                 FreeArgs(args, nUsed);
  1944.                 nUsed = 0;
  1945.                 free_redirections(ar, nRedirections);
  1946.                 nRedirections = 0;
  1947.             }
  1948.             else
  1949.             {
  1950.                 FreeArgs(args, nUsed);
  1951.                 free(args);
  1952.                 free_redirections(ar, nRedirections);
  1953.                 return retval;
  1954.             }
  1955.             break;
  1956.  
  1957.         case TOKEN_OK:
  1958.             args[nUsed++] = pchArg;
  1959.             if (nUsed == 1 &&
  1960.                expand_alias(args[0], pchCmd, &retval))
  1961.             {
  1962.                 FreeArgs(args, nUsed);
  1963.                 free(args);
  1964.                 free_redirections(ar, nRedirections);
  1965.                 return retval;
  1966.             }
  1967.             break;
  1968.  
  1969.         case TOKEN_FDTO:
  1970.         case TOKEN_APPENDTO:
  1971.         case TOKEN_REDIRTO:
  1972.         case TOKEN_REDIRFROM:
  1973.         case TOKEN_FDFROM:
  1974.             nFileToken = GetArg(&pchCmd, &pchArg, &bRunOn);
  1975.             if (nFileToken != TOKEN_OK)
  1976.             {
  1977.                 fprintf(stderr, "Redirection syntax error\n");
  1978.                 if (pchArg)
  1979.                     free(pchArg);
  1980.                 FreeArgs(args, nUsed);
  1981.                 free(args);
  1982.                 free_redirections(ar, nRedirections);
  1983.                 return -1;
  1984.             }
  1985.             bRunOn = FALSE;
  1986.             nFile = -1;
  1987.             if (bLastRunOn)
  1988.             {
  1989.                 bNonDigit = FALSE;
  1990.                 for (i = 0; args[nUsed - 1][i]; i++)
  1991.                 {
  1992.                     if (!isdigit(args[nUsed - 1][i]))
  1993.                     {
  1994.                         bNonDigit = TRUE;
  1995.                         break;
  1996.                     }
  1997.                 }
  1998.                 if (!bNonDigit && args[nUsed - 1][0])
  1999.                 {
  2000.                     nFile = atoi(args[nUsed - 1]);
  2001.                     free(args[--nUsed]);
  2002.                     args[nUsed] = 0;
  2003.                     if (nFile > 2)
  2004.                     {
  2005.                         fprintf(stderr, "Silly redirection\n");
  2006.                         FreeArgs(args, nUsed);
  2007.                         free(args);
  2008.                         free(pchArg);
  2009.                         free_redirections(ar, nRedirections);
  2010.                         return -1;
  2011.                     }
  2012.                 }
  2013.             }
  2014.             if (nFile == -1)
  2015.             {
  2016.                 switch(nToken)
  2017.                 {
  2018.                 case TOKEN_FDTO:
  2019.                 case TOKEN_APPENDTO:
  2020.                 case TOKEN_REDIRTO:
  2021.                     nFile = 1;
  2022.                     break;
  2023.  
  2024.                 case TOKEN_REDIRFROM:
  2025.                 case TOKEN_FDFROM:
  2026.                     nFile = 2;
  2027.                     break;
  2028.                 }
  2029.             }
  2030.             for (i = 0; i < nRedirections; i++)
  2031.             {
  2032.                 if (ar[i].fd == nFile)
  2033.                 {
  2034.                     fprintf(stderr, "Ambiguous redirection\n");
  2035.                     free(pchArg);
  2036.                     FreeArgs(args, nUsed);
  2037.                     free(args);
  2038.                     free_redirections(ar, nRedirections);
  2039.                     return -1;
  2040.                 }
  2041.             }
  2042.             ar[nRedirections].fd = nFile;
  2043.             switch(nToken)
  2044.             {
  2045.             case TOKEN_FDFROM:
  2046.             case TOKEN_FDTO:
  2047.                 ar[nRedirections].pchFile = 0;
  2048.                 ar[nRedirections].fdSource = atoi(pchArg);
  2049.                 free(pchArg);
  2050.                 break;
  2051.  
  2052.             case TOKEN_APPENDTO:
  2053.             case TOKEN_REDIRTO:
  2054.             case TOKEN_REDIRFROM:
  2055.                 ar[nRedirections].pchFile = pchArg;
  2056.                 ar[nRedirections].fdSource = -1;
  2057.                 break;
  2058.             }
  2059.             switch(nToken)
  2060.             {
  2061.             case TOKEN_REDIRFROM:
  2062.             case TOKEN_FDFROM:
  2063.                 ar[nRedirections].iMode = O_RDONLY;
  2064.                 break;
  2065.  
  2066.             case TOKEN_REDIRTO:
  2067.             case TOKEN_FDTO:
  2068.                 ar[nRedirections].iMode = O_WRONLY | O_CREAT | O_TRUNC;
  2069.                 break;
  2070.  
  2071.             case TOKEN_APPENDTO:
  2072.                 ar[nRedirections].iMode = O_WRONLY | O_CREAT | O_APPEND;
  2073.                 break;
  2074.             }
  2075.             nRedirections++;
  2076.             break;
  2077.  
  2078.         case TOKEN_ERROR:
  2079.             FreeArgs(args, nUsed);
  2080.             free(args);
  2081.             fprintf(stderr, "Syntax error\n");
  2082.             free_redirections(ar, nRedirections);
  2083.             return -1;
  2084.         }
  2085.     }
  2086. }
  2087.  
  2088.  
  2089.